<?php
    /**
     *This behavior assumes 0 and 1 values for unpublish and publish
     * onAutoModeration is callback called on moderated model. 
     */
    class AutoModeratorBehavior extends ModelBehavior
    {
        private $defaults = array(
                "statusField"=>"status",
                "hasMany"=>true,
                "hasOne"=>true,
                "autoRecursive" => true,
                "assocModels"=>array());
        var $settings = array();
        
        function setup(AppModel $model,$config=array())
        {
            $this->settings[$model->alias] = am($this->defaults,$config);
        }
        private function getSettings(AppModel $model)
        {
            return $this->settings[$model->alias];
        }
        function afterSave(AppModel $model, $created) 
        {
            parent::afterSave($model, $created);
            $settings = $this->getSettings($model);
            $statusField = $settings['statusField'];
            if($created || !isset($model->data[$model->alias][$statusField]))
            {
                return;
            }
            $statusValue = $model->data[$model->alias][$statusField];
            if($statusValue)
            {
                $this->publishDependent($model, $model->id);
            }
            //entity is being unpublished.
            else
            {
                $this->unPublishDependent($model, $model->id);
            }
            
        }
        /**
         *
         * @param AppModel $model 
         * @return Array<AppModel>
         */
        private function getDependentModels(AppModel $model)
        {
             $settings = $this->getSettings($model);
             $modelsName = array();
             if($settings['assocModels'])
             {
                 $modelsName = $settings['assocModels'];
             }
             if(!$modelsName)
             {
                 $modelsName = array();
             }
             if($settings['hasMany'])
             {
                $hasManyModels =  $model->getAssociated("hasMany");
                $modelsName = am($modelsName,$hasManyModels);
             }
             if($settings['hasOne'])
             {
                $hasOneModels =  $model->getAssociated("hasOne");
                $modelsName = am($modelsName,$hasOneModels);
             }
             $models = array();
             foreach($modelsName as $modelName)
             { 
                 if(isset($model->$modelName))
                 {
                     $modelInstance = $model->{$modelName};
                     if($modelInstance instanceof AppModel)
                     {
                         $models[$modelName] = $modelInstance;
                     }
                 }
             }
             return $models;
        }
        private function unPublishDependent(AppModel $model,$id)
        {
            
            $ModeratorModel = $this->getModerator();
            $DependentModels = $this->getDependentModels($model);
            $foreginKey = $model->foreignKey;
            $settings = $this->getSettings($model);
            $statusField = $settings['statusField'];
            foreach($DependentModels as $DependentModel)
            {
              /* @var $DependentModel AppModel */  
              $DependentModel;
              if($DependentModel->hasField($statusField) == false)
              {
                  continue;
              }
              $entitiesIds = $DependentModel->find("list",array("conditions"=>array($foreginKey => $id,$statusField=>1),'fields'=>array($DependentModel->primaryKey)));
              foreach($entitiesIds as $entityId)
              {
                  $ModeratorModel->markDependentModeration($model, $id, $DependentModel, $entityId);
                  if($settings['autoRecursive'] && $DependentModel->Behaviors->attached("AutoModerator"))
                  {
                     $DependentModel->id = $entityId;
                     $DependentModel->saveField($statusField,0,false,false);
                     $this->unPublishDependent($DependentModel,$entityId);
                  }else
                  {
                      $DependentModel->id = $entityId;
                      $DependentModel->saveField($statusField,0);
                  }
              }
              if($settings['autoRecursive'] && method_exists($DependentModel,"onAutoModeration"))
              {
                    $DependentModel->onAutoModeration($model,$id,$entitiesIds,0);
              }
            }
            if($settings['autoRecursive'])
            {
                $model->refershCounters($id);
            }
        }
        
        private function publishDependent(AppModel $model,$id)
        {
            $ModeratorModel = $this->getModerator();
            $settings = $this->getSettings($model);
            $statusField = $settings['statusField'];
            $foreginKey = $model->foreignKey;
            $DependentModels = $this->getDependentModels($model);
            $publishList = $ModeratorModel->getDependents($model,$id);
            foreach($publishList as $modelName => $modelEntities)
            {
                if(!isset($DependentModels[$modelName]))
                {
                    continue;
                }
                $DependentModel = $DependentModels[$modelName];
                $entitiesIds = $DependentModel->find("list",array("conditions"=>array($foreginKey => $id,$statusField=>0,$DependentModel->primaryKey => $modelEntities),'fields'=>array($DependentModel->primaryKey)));
                foreach($entitiesIds as $entityId)
                {
                    if($settings['autoRecursive'] && $DependentModel->Behaviors->attached("AutoModerator"))
                    {
                        $DependentModel->id = $entityId;
                        $DependentModel->saveField($statusField,1,false,false);
                        $this->publishDependent($DependentModel, $entityId);
                        $DependentModel->clearRecordCache($entityId,true);
                    }else
                    {
                        $DependentModel->id = $entityId;
                        $DependentModel->saveField($statusField,1);
                    }
                }
                if($settings['autoRecursive'] && method_exists($DependentModel,"onAutoModeration"))
                {
                    $DependentModel->onAutoModeration($model,$id,$entitiesIds,1);
                }
            }
            if($settings['autoRecursive'])
            {
                $model->refershCounters($id);
                @$model->clearRecordCache($id,true);
            }
            $ModeratorModel->removeMarkedDepedent($model,$id);
        }
        /**
         * @return AutoModerationHelper
         */
        private function getModerator()
        {
          return cri("AutoModerator.AutoModerationHelper");   
        }
    }
?>
